package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

/*单行查询db.QueryRow()执行一次查询，并期望返回最多一行结果（即Row）。
QueryRow总是返回非nil的值，直到返回值的Scan方法被调用时，才会返回被延迟的错误。*/

// 定义一个全局对象db
var dbl *sql.DB

// 定义一个初始化数据库函数
func initDBl() (err error) {
	dsn := "root:123456@tcp(127.0.0.1:3306)" + "/go_db?charset=utf8mb4&parseTime=true"
	//不会校验账号密码正确
	//注意!!!这里不要使用 := ，我们是全局变量赋值，然后在main函数这种使用全局变量db
	dbl, err = sql.Open("mysql", dsn)
	if err != nil {
		return err
	}

	// See "Important settings" section.
	dbl.SetMaxIdleConns(10)               //保持连接的最大空闲连接数
	dbl.SetMaxOpenConns(10)               //最大连接数
	dbl.SetConnMaxLifetime(7 * time.Hour) //闲置连接的最大存活时间

	err = dbl.Ping() //尝试与数据库连接
	if err != nil {
		return err
	}
	return nil
}

// 定义一个结构体
type user struct {
	id       int
	username string
	password string
}

// 查询一条用户数据
func queryRowDemo(n int) {
	sqlStr := "select id,username,password from user_tbl where id =?"
	var u user
	//确保QueryRow之后的调用方Scan法，否则持有的数据库连接不会被释放
	err := dbl.QueryRow(sqlStr, n).Scan(&u.id, &u.username, &u.password)
	if err != nil {
		fmt.Printf("scan failed,err:%v\n", err)
		return
	}
	fmt.Printf("id:%d name:%s password:%s", u.id, u.username, u.password)
}

// 查询多行
func queryManyRow(n int) {
	s := "select * from user_tbl where id >= ?"
	r, err := dbl.Query(s, n)
	defer r.Close() //关闭释放
	if err != nil {
		fmt.Printf("err:%v\n", err)
	} else {
		//循环读取
		for r.Next() {
			var u user
			err := r.Scan(&u.id, &u.username, &u.password)
			if err != nil {
				fmt.Printf("scan failed,err:%v\n", err)
				return
			}
			fmt.Printf("id:%d name:%s password:%s\n", u.id, u.username, u.password)
		}
	}

}
func main() {
	err := initDBl()
	if err != nil {
		fmt.Printf("初始化失败!,err:%v\n", err)
	} else {
		fmt.Println("初始化成功...")
	}
	queryRowDemo(1)
	queryManyRow(2)
}
